from odoo import fields, models, api
from ast import literal_eval
from odoo.osv.expression import AND

class ProductReplaceRule(models.Model):
    _name = 'product.replace.rule'
    _description = '产品替换规则'
    _inherit = ['mail.thread', 'mail.activity.mixin']

    name = fields.Char(string='名称')
    convertible_ratio = fields.Float(string='转换比例', default=1)
    rule_domain = fields.Char(string='产成品预筛选条件')
    product_domain = fields.Char(string='物料预筛选条件')
    priority_lines = fields.One2many('product.priority.line', 'rule_id', string='替代物料预筛选条件')
    active = fields.Boolean(string="启用", default=True)
    check_quant = fields.Boolean(string="校验库存", default=False, help='勾选后，会过滤库存不足的目标产品')
    check_attributes = fields.Boolean(string='校验产品属性', default=False, help='勾选后，会校验原产品与目标产品属性必须一致')
    product_attribute_lines = fields.One2many('s.material.coding.attribute.line', 'rule_id', string='产品属性')
    sequence = fields.Integer(default=10, string="优先级")

    def _get_match_rules(self, order_line, product):
        match_rules = self.env['product.replace.rule']
        rules = self.env['product.replace.rule'].sudo().search([])
        for rule in rules:
            if rule.rule_domain:
                domain = AND([literal_eval(rule.rule_domain), [('id', '=', order_line.id)]])
                res = self.env['sale.order.line'].search(domain)
                product_domain = AND([literal_eval(rule.product_domain), [('product_variant_ids', '=', product.id)]])
                product_res = self.env['product.template'].search(product_domain)
                if res and product_res:
                    match_rules |= rule
        return match_rules

    def _get_match_rule(self, order_line, product):
        match_rules = self._get_match_rules(order_line, product)
        if match_rules:
            return match_rules.sorted(key=lambda x: x.sequence)[0]
        else:
            return False

    # 根据传入规则的替代物料预筛选条件匹配可替换物料，并根据规则明细中物料优先级筛选条件排序
    def _get_replace_products(self):
        replace_products = self.env['product.product']
        if self.priority_lines:
            for priority_line in self.priority_lines.sorted(lambda x: x.sequence):
                domain = literal_eval(priority_line.priority_domain)
                product_templates = self.env['product.template'].sudo().search(domain)
                products = self.env['product.product'].search([('product_tmpl_id', 'in', product_templates.ids)])
                if priority_line.sort_field and priority_line.sort_field_lvt:
                    details = products[priority_line.sort_field.name].sorted(lambda x: x[priority_line.sort_field_lvt.name], reverse=priority_line.reverse)
                    product_templates = details[priority_line.sort_field.relation_field]
                    products = product_templates.product_variant_ids
                elif priority_line.sort_field:
                    products = products.sorted(lambda x: x[priority_line.sort_field.name], reverse=priority_line.reverse)
                replace_products |= products
        return replace_products